package com.wodan.zhongjinjicang.common.orm.command.write;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.concurrent.Callable;

import org.apache.ibatis.mapping.SqlCommandType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.util.Assert;

import com.wodan.zhongjinjicang.common.orm.RdsCommonWriteDao;
import com.wodan.zhongjinjicang.common.orm.command.base.AbstractSqlCommandExecutor;
import com.wodan.zhongjinjicang.common.orm.metadata.MethodMetaData;
import com.wodan.zhongjinjicang.common.orm.metadata.TableFieldMetaData;
import com.wodan.zhongjinjicang.common.orm.metadata.TableMetaData;
import com.wodan.zhongjinjicang.common.orm.utils.ReflectionUtils;
import com.wodan.zhongjinjicang.common.orm.utils.SqlGenernateUtils;

/**
 * 插入操作的执行者
 * 
 * @ClassName: SqlInsertExecutor
 * @author Administrator
 * @date 2015-11-5 下午4:43:12
 * @history
 * 
 */
public class SqlInsertExecutor extends AbstractSqlCommandExecutor {
	private static final Logger LOGGER = LoggerFactory.getLogger(SqlInsertExecutor.class);

	@Override
	protected Object doExecute(final TableMetaData tableMetaData, MethodMetaData methodMetaData,
			final Object[] args) {
		Assert.notEmpty(args);
		Assert.isTrue(args.length == 1);

		final Object entity = args[0];

		// 解析bean内容为数据库的字段内容
		Map<String, Object> fieldValueMap = resolveBeanToColumnNameMap(entity, tableMetaData);
		final String tableName = tableMetaData.getTableName();
		final String[] columnNames = fieldValueMap.keySet().toArray(new String[fieldValueMap.size()]);
		final Object[] values = fieldValueMap.values().toArray(new Object[fieldValueMap.size()]);

		// 生成sql语句插入数据库
		final String insertSql = super.createCachedSqlScript(new Callable<String>() {
			@Override
			public String call() throws Exception {
				return SqlGenernateUtils.createInsertSql(tableName, columnNames);
			}
		}, tableName, columnNames);

		LOGGER.debug("execute sql: [{}]", insertSql);

		// 判断id是否为自增长
		if (isIdAutoIncrement(tableMetaData, fieldValueMap)) {
			return jdbcTemplate.execute(new ConnectionCallback<Integer>() {
				@Override
				public Integer doInConnection(Connection con) throws SQLException, DataAccessException {
					PreparedStatement pstmt = con.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
					for (int i = 0; i < values.length; i++) {
						pstmt.setObject(i + 1, values[i]);
					}

					int result = pstmt.executeUpdate();
					// 影响行数为0，插入失败
					if (result == 0) {
						return result;
					}

					// 插入成功，获取自增的key
					ResultSet generatedKeys = pstmt.getGeneratedKeys();
					if (generatedKeys.next()) {
						Object genernatedId = generatedKeys.getObject(1);
						TableFieldMetaData idField = tableMetaData.getIdField();
						idField.writeFieldValue(entity, genernatedId);
					}

					return result;
				}
			});
		} else {
			return jdbcTemplate.update(insertSql, values);
		}
	}

	private boolean isIdAutoIncrement(TableMetaData tableMetaData, Map<String, Object> fieldValueMap) {
		TableFieldMetaData idField = tableMetaData.getIdField();
		if (idField == null) {
			return false;
		}

		if (fieldValueMap.get(idField.getColumnName().toString()) != null) {
			// 如果插入时已经传入id,则不返回id
			return false;
		} else {
			// 如果插入时未未传入id，则返回自增id
			return true;
		}
	}

	@Override
	public Method getProxyMethod() {
		return ReflectionUtils.findMethod(RdsCommonWriteDao.class, "insert", Object.class);
	}
	
	@Override
	public SqlCommandType getSqlCommandType() {
		return SqlCommandType.INSERT;
	}
}
